package service

import (
	database "MyBlogv2/common/database"
	"MyBlogv2/common/helper"
	"MyBlogv2/common/milvus"
	"MyBlogv2/common/models"
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"

	minio "MyBlogv2/common/minio"

	"github.com/gin-gonic/gin"
	"github.com/jmoiron/sqlx"
	"github.com/openai/openai-go"
	"github.com/openai/openai-go/option"
	ark "github.com/sashabaranov/go-openai"
	"gopkg.in/yaml.v2"
)

// SessionRow 数据库行结构体
type SessionRow struct {
	SessionID   string    `db:"session_id"`
	SessionName string    `db:"session_name"`
	Content     string    `db:"content"`
	UserID      int       `db:"user_id"`
	CreatedAt   time.Time `db:"created_at"`
	UpdatedAt   time.Time `db:"updated_at"`
}

// API请求和响应结构体
type ChatRequest struct {
	Message   string `json:"message" binding:"required"`
	SessionID string `json:"session_id"`
	Model     string `json:"model"`
}

type ChatResponse struct {
	Message   string `json:"message"`
	SessionID string `json:"session_id"`
	Success   bool   `json:"success"`
	Error     string `json:"error,omitempty"`
}

type SessionListResponse struct {
	Sessions []ChatSession `json:"sessions"`
	Success  bool          `json:"success"`
	Error    string        `json:"error,omitempty"`
}

type SessionResponse struct {
	Session ChatSession `json:"session"`
	Success bool        `json:"success"`
	Error   string      `json:"error,omitempty"`
}

// ChatSession 表示一个对话会话
type ChatSession struct {
	ID        string                      `json:"id"`
	Name      string                      `json:"name"`
	History   []ark.ChatCompletionMessage `json:"history"`
	CreatedAt time.Time                   `json:"created_at"`
	UpdatedAt time.Time                   `json:"updated_at"`
}

// 初始化聊天机器人配置
func InitAIAgentDatabase() {
	// 初始化数据库连接
	if err := database.InitDB(); err != nil {
		fmt.Printf("数据库初始化失败: %v\n", err)
		panic(err)
	}
	fmt.Println("数据库连接成功!")
}

// AIAgent 增强的AI助手，支持工具调用
type AIChat struct {
	client    *ark.Client
	model     string
	history   []ark.ChatCompletionMessage
	maxTokens int
	sessionID string
	db        *sqlx.DB
	tools     []ark.Tool // 可用工具列表
}

// ToolCall 工具调用结果
type ToolCall struct {
	ID       string           `json:"id"`
	Type     string           `json:"type"`
	Function ToolCallFunction `json:"function"`
}

type ToolCallFunction struct {
	Name      string `json:"name"`
	Arguments string `json:"arguments"`
}

// ToolResult 工具执行结果
type ToolResult struct {
	ToolCallID string `json:"tool_call_id"`
	Content    string `json:"content"`
}

var agent_config, _ = LoadAPIConfig()

// LoadAPIConfig 从api_config.yaml文件加载配置
func LoadAPIConfig() (map[string]map[string]map[string]string, error) {
	config := map[string]map[string]map[string]string{}

	// 获取当前工作目录
	workDir, err := os.Getwd()
	if err != nil {
		log.Println("获取工作目录失败:", err)
		return nil, err
	}

	// 构建配置文件的绝对路径
	configPath := filepath.Join(workDir, "api_config.yaml")

	// 读取配置文件
	data, err := ioutil.ReadFile(configPath)
	if err != nil {
		log.Println("读取api_config.yaml文件失败:", err)
		return nil, err
	}

	// 解析YAML配置
	if err := yaml.Unmarshal(data, config); err != nil {
		log.Println("解析api_config.yaml文件失败:", err)
		return nil, err
	}
	log.Println("api_config.yaml文件读取成功:", configPath)

	return config, nil
}

// generateSessionID 生成唯一的会话ID
func generateSessionID() string {
	return fmt.Sprintf("session_%d", time.Now().UnixNano())
}

// NewAIChatWithSession 创建AI Chat实例，可选择指定sessionID
func NewAIChatWithSession(apiKey, baseURL, model string, sessionID string) *AIChat {
	// // 配置本地代理
	// proxyURL, err := url.Parse("http://127.0.0.1:7897") // 请根据您的代理端口修改
	// if err != nil {
	// 	fmt.Printf("代理URL解析错误: %v\n", err)
	// 	return nil
	// }

	// // 创建HTTP传输器并设置代理
	// transport := &http.Transport{
	// 	Proxy: http.ProxyURL(proxyURL),
	// }

	// // 包装transport添加User-Agent
	// customTransport := &userAgentTransport{
	// 	RoundTripper: transport,
	// 	userAgent:    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
	// }
	// // 创建HTTP客户端
	// httpClient := &http.Client{
	// 	Transport: customTransport,
	// }

	config := ark.DefaultConfig(apiKey)
	config.BaseURL = baseURL
	// config.HTTPClient = httpClient
	client := ark.NewClientWithConfig(config)

	// 初始化系统消息，包含工具使用说明
	systemMessage := `你是一个AI助手，可以帮助用户回答关于博客文章的问题。

你可以使用以下工具：
1. search_articles - 根据关键词搜索博客文章
2. get_article_detail - 获取博客文章详细内容
3. generate_image - 生成图片


如果是关于其他问题，你可以直接回答用户问题。

当用户询问关于博客文章的问题时，你应该：
1. 首先使用search_articles工具搜索相关文章
2. 如果需要更详细的信息，可以使用get_article_detail获取具体文章内容
3. 基于找到的文章内容回答用户问题
4. 如果找不到相关信息，诚实地告诉用户

请用中文回答用户的问题。`

	history := []ark.ChatCompletionMessage{
		{
			Role:    ark.ChatMessageRoleSystem,
			Content: systemMessage,
		},
	}

	// 定义可用工具
	tools := []ark.Tool{
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name:        "search_articles",
				Description: "根据关键词搜索博客文章",
				Parameters: map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"keyword": map[string]interface{}{
							"type":        "string",
							"description": "搜索关键词",
						},
						"limit": map[string]interface{}{
							"type":        "integer",
							"description": "返回结果数量限制，默认10",
						},
					},
					"required": []string{"keyword"},
				},
			},
		},
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name:        "get_article_detail",
				Description: "获取指定文章的详细内容",
				Parameters: map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"article_id": map[string]interface{}{
							"type":        "integer",
							"description": "文章ID",
						},
					},
					"required": []string{"article_id"},
				},
			},
		},
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name:        "generate_image",
				Description: "生成图片，如果用户的提示词比较简单，你需要完善提示词，使用完毕后系统会自动向用户展示图片（在你后续的消息上方），所以你不需要再重复图片的URL",
				Parameters: map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"prompt": map[string]interface{}{
							"type":        "string",
							"description": "生成图片的提示",
						},
					},
					"required": []string{"prompt"},
				},
			},
		},
	}

	// 如果没有提供sessionID，生成一个新的
	if sessionID == "" {
		sessionID = generateSessionID()
	}

	return &AIChat{
		client:    client,
		model:     model,
		history:   history,
		maxTokens: 5000,
		sessionID: sessionID,
		db:        database.Db,
		tools:     tools,
	}
}

// 工具函数实现
// SearchArticles 搜索文章
func (agent *AIChat) SearchArticles(keyword string, limit int) (string, error) {

	posts, err := milvus.MilvusDB.SearchSimilarVectorsByText(keyword, 5)
	if err != nil {
		return "", fmt.Errorf("向量相似度搜索文章失败: %v", err)
	}

	postIds := make([]int64, len(posts))
	for i, post := range posts {
		postIds[i] = post.PostID
	}

	// 使用sqlx.In()处理IN子句中的切片参数
	query, args, err := sqlx.In(`
		SELECT a.id, a.article_title, a.article_content, a.article_cover,
		    c.category_name
		FROM t_article a
		LEFT JOIN t_category c ON a.category_id = c.id
		WHERE a.status = 1 AND a.is_deleted = 0
		AND a.id IN (?)
		ORDER BY a.visit_count DESC
	`, postIds)
	if err != nil {
		return "", fmt.Errorf("构建查询语句失败: %v", err)
	}

	var articles []models.SearchArticleByContentVo
	err = agent.db.Select(&articles, query, args...)

	if err != nil {
		return "", fmt.Errorf("搜索文章失败: %v", err)
	}

	if len(articles) == 0 {
		return fmt.Sprintf("没有找到包含关键词 '%s' 的文章", keyword), nil
	}

	result := fmt.Sprintf("找到 %d 篇相关文章：\n", len(articles))
	for i, article := range articles {
		// 生成文章链接
		articleURL := fmt.Sprintf("http://127.0.0.1:99/article/%d", article.Id)

		result += fmt.Sprintf("%d. <a href='%s' target='_blank' class='article-link'>%s</a>\n ID: %d\n   分类: %s\n   封面: %s\n",
			i+1, articleURL, article.ArticleTitle, article.Id, article.CategoryName, article.ArticleCover)
	}

	return result, nil
}

// GetArticleDetail 获取文章详情
func (agent *AIChat) GetArticleDetail(articleID int) (string, error) {
	var article models.ArticleDetailVo
	err := agent.db.Get(&article, `
		SELECT a.id, a.user_id, a.category_id, a.article_title, 
		       a.article_type, a.article_content, 
		       a.article_cover, a.is_top, a.visit_count,
		       a.created_at, a.updated_at, c.category_name
		FROM t_article a
		LEFT JOIN t_category c ON a.category_id = c.id
		WHERE a.id = ? AND a.status = 1 AND a.is_deleted = 0
	`, articleID)

	if err != nil {
		if err == sql.ErrNoRows {
			return fmt.Sprintf("文章 ID %d 不存在或已被删除", articleID), nil
		}
		return "", fmt.Errorf("获取文章详情失败: %v", err)
	}

	// 获取文章标签
	var tags []string
	err = agent.db.Select(&tags, `
		SELECT t.tag_name
		FROM t_tag t
		INNER JOIN t_article_tag at ON t.id = at.tag_id
		WHERE at.article_id = ?
	`, articleID)

	if err != nil {
		// 标签获取失败不影响主要功能
		tags = []string{}
	}

	// 获取统计信息
	var likeCount, favoriteCount, commentCount int
	agent.db.Get(&likeCount, "SELECT COUNT(*) FROM t_like WHERE type_id = ? AND type = 1", articleID)
	agent.db.Get(&favoriteCount, "SELECT COUNT(*) FROM t_favorite WHERE type_id = ? AND type = 1", articleID)
	agent.db.Get(&commentCount, "SELECT COUNT(*) FROM t_comment WHERE type_id = ? AND type = 1", articleID)

	result := fmt.Sprintf(`文章详情：
标题: %s
分类: %s
标签: %s
访问量: %d
点赞数: %d
收藏数: %d
评论数: %d
创建时间: %s
更新时间: %s

文章内容:
%s`,
		article.ArticleTitle,
		article.CategoryName,
		strings.Join(tags, ", "),
		article.VisitCount,
		likeCount,
		favoriteCount,
		commentCount,
		article.CreateTime.String(),
		article.UpdateTime.String(),
		article.ArticleContent)

	return result, nil
}

func (agent *AIChat) GenerateImage(prompt string) (string, error) {
	client := openai.NewClient(
		option.WithAPIKey(agent_config["image"]["ark"]["api_key"]),
		option.WithBaseURL(agent_config["image"]["ark"]["base_url"]),
	)

	req := openai.ImageGenerateParams{
		Model:          agent_config["image"]["ark"]["model"],
		Prompt:         prompt,
		Size:           openai.ImageGenerateParamsSize1024x1024,
		ResponseFormat: openai.ImageGenerateParamsResponseFormatURL,
	}

	resp, err := client.Images.Generate(context.Background(), req)
	if err != nil {
		return "", err
	}
	newURL, err := downloadImageAndUploadToMinIO(resp.Data[0].URL)
	if err != nil {
		return "", err
	}

	return newURL, nil
}

// ExecuteTool 执行工具调用
func (agent *AIChat) ExecuteTool(toolCall ark.ToolCall) (string, error) {
	if toolCall.Function.Name == "" {
		return "", fmt.Errorf("工具调用缺少函数信息")
	}

	functionName := toolCall.Function.Name
	arguments := toolCall.Function.Arguments

	// 解析参数
	var params map[string]interface{}
	if err := json.Unmarshal([]byte(arguments), &params); err != nil {
		return "", fmt.Errorf("解析工具参数失败: %v", err)
	}

	switch functionName {
	case "search_articles":
		keyword, _ := params["keyword"].(string)
		limit := 10
		if l, ok := params["limit"].(float64); ok {
			limit = int(l)
		}
		return agent.SearchArticles(keyword, limit)

	case "get_article_detail":
		articleID := int(params["article_id"].(float64))
		return agent.GetArticleDetail(articleID)

	case "generate_image":
		prompt, _ := params["prompt"].(string)
		return agent.GenerateImage(prompt)

	default:
		return "", fmt.Errorf("未知的工具函数: %s", functionName)
	}
}

// // ChatWithToolsStream 支持工具调用的流式聊天（模拟流式，用于兼容）
// func (agent *AIChat) ChatWithToolsStream(message string, writer gin.ResponseWriter) error {
// 	// 添加用户消息
// 	agent.history = append(agent.history, ark.ChatCompletionMessage{
// 		Role:    ark.ChatMessageRoleUser,
// 		Content: message,
// 	})

// 	ctx := context.Background()

// 	for {
// 		// 创建聊天完成请求，包含工具
// 		req := ark.ChatCompletionRequest{
// 			Model:     agent.model,
// 			Messages:  agent.history,
// 			MaxTokens: agent.maxTokens,
// 			Tools:     agent.tools,
// 		}

// 		// 发送请求
// 		resp, err := agent.client.CreateChatCompletion(ctx, req)
// 		if err != nil {
// 			return fmt.Errorf("AI请求失败: %v", err)
// 		}

// 		// 处理响应
// 		assistantMessage := resp.Choices[0].Message

// 		// 如果有文本内容，先流式输出
// 		if assistantMessage.Content != "" {
// 			agent.streamContent(assistantMessage.Content, writer, fmt.Sprintf("response_%d", time.Now().UnixNano()))
// 		}

// 		// 添加助手消息到历史
// 		agent.history = append(agent.history, assistantMessage)

// 		// 检查是否有工具调用
// 		if len(assistantMessage.ToolCalls) > 0 {
// 			// 流式输出工具调用过程
// 			for _, toolCall := range assistantMessage.ToolCalls {
// 				// 输出工具调用开始信息
// 				toolStartData := map[string]interface{}{
// 					"type":       "tool_start",
// 					"tool_name":  toolCall.Function.Name,
// 					"session_id": agent.sessionID,
// 					"bubble_id":  fmt.Sprintf("tool_%s_%d", toolCall.Function.Name, time.Now().UnixNano()),
// 				}
// 				jsonData, _ := json.Marshal(toolStartData)
// 				writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
// 				writer.Flush()

// 				// 执行工具调用
// 				toolResult, err := agent.ExecuteTool(toolCall)
// 				if err != nil {
// 					toolResult = fmt.Sprintf("工具执行失败: %v", err)
// 				}

// 				if toolCall.Function.Name != "get_article_detail" {
// 					// 流式输出工具结果
// 					agent.streamToolResult(toolResult, writer, toolStartData["bubble_id"].(string))
// 				}

// 				// 添加工具结果到历史
// 				agent.history = append(agent.history, ark.ChatCompletionMessage{
// 					Role:       ark.ChatMessageRoleTool,
// 					Content:    toolResult,
// 					ToolCallID: toolCall.ID,
// 					Name:       toolCall.Function.Name,
// 				})

// 				// 输出工具调用结束信息
// 				toolEndData := map[string]interface{}{
// 					"type":       "tool_end",
// 					"tool_name":  toolCall.Function.Name,
// 					"session_id": agent.sessionID,
// 					"bubble_id":  toolStartData["bubble_id"],
// 				}
// 				jsonData, _ = json.Marshal(toolEndData)
// 				writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
// 				writer.Flush()
// 			}

// 			// 继续下一轮迭代，让AI基于工具结果决定是否需要再次调用工具
// 			continue
// 		} else {
// 			// 没有工具调用，对话结束
// 			break
// 		}
// 	}
// 	return nil
// }

// ChatWithToolsStreamReal 真正的流式聊天，支持工具调用和思考过程展示
func (agent *AIChat) ChatWithToolsStreamReal(message string, writer gin.ResponseWriter) error {
	// 添加用户消息
	agent.history = append(agent.history, ark.ChatCompletionMessage{
		Role:    ark.ChatMessageRoleUser,
		Content: message,
	})

	ctx := context.Background()
	maxIterations := 10 // 防止无限循环
	iteration := 0
	for iteration < maxIterations {
		iteration++

		// 创建流式聊天完成请求，包含工具
		req := ark.ChatCompletionRequest{
			Model:     agent.model,
			Messages:  agent.history,
			Tools:     agent.tools,
			Stream:    true, // 开启流式模式
		}

		// 创建流式请求
		stream, err := agent.client.CreateChatCompletionStream(ctx, req)
		if err != nil {
			fmt.Println(err)
			return fmt.Errorf("AI流式请求失败: %v", err)
		}
		var fullContent strings.Builder
		var fullReasoning strings.Builder
		var toolCalls []ark.ToolCall
		var currentBubbleID string
		var thinkingBubbleID string
		var thinkingStarted bool
		toolBubbleIDs := make(map[int]string) // 存储每个工具调用的bubble_id
		// 接收流式响应
		for {
			response, err := stream.Recv()
			if err == io.EOF {
				break
			}
			if err != nil {
				stream.Close()
				return fmt.Errorf("接收流式响应失败: %v", err)
			}

			if len(response.Choices) == 0 {
				continue
			}

			delta := response.Choices[0].Delta

			// 处理 thinking/reasoning 内容（必须在普通内容之前）
			if delta.ReasoningContent != "" {
				fullReasoning.WriteString(delta.ReasoningContent)

				// 发送 thinking_start 信号（仅首次）
				if !thinkingStarted {
					thinkingBubbleID = fmt.Sprintf("thinking_%d", time.Now().UnixNano())
					thinkingStartData := map[string]interface{}{
						"type":       "thinking_start",
						"session_id": agent.sessionID,
						"bubble_id":  thinkingBubbleID,
					}
					jsonData, _ := json.Marshal(thinkingStartData)
					writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
					writer.Flush()
					thinkingStarted = true
				}

				// 流式输出 thinking 内容
				thinkingData := map[string]interface{}{
					"type":       "thinking",
					"content":    delta.ReasoningContent,
					"session_id": agent.sessionID,
					"bubble_id":  thinkingBubbleID,
				}
				jsonData, _ := json.Marshal(thinkingData)
				writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
				writer.Flush()
			}

			// 处理内容流式输出
			if delta.Content != "" {
				// 如果之前有 thinking，先发送 thinking_end
				if thinkingStarted && thinkingBubbleID != "" {
					thinkingEndData := map[string]interface{}{
						"type":       "thinking_end",
						"session_id": agent.sessionID,
						"bubble_id":  thinkingBubbleID,
					}
					jsonData, _ := json.Marshal(thinkingEndData)
					writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
					writer.Flush()
					thinkingBubbleID = "" // 重置，避免重复发送
				}

				// 普通内容
				fullContent.WriteString(delta.Content)

				if currentBubbleID == "" {
					currentBubbleID = fmt.Sprintf("response_%d", time.Now().UnixNano())
				}

				contentData := map[string]interface{}{
					"type":       "content",
					"content":    delta.Content,
					"session_id": agent.sessionID,
					"bubble_id":  currentBubbleID,
				}
				jsonData, _ := json.Marshal(contentData)
				writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
				writer.Flush()
			}

			// 处理工具调用（流式模式下逐步累积）
			if len(delta.ToolCalls) > 0 {
				// 如果之前有 thinking，先发送 thinking_end
				if thinkingStarted && thinkingBubbleID != "" {
					thinkingEndData := map[string]interface{}{
						"type":       "thinking_end",
						"session_id": agent.sessionID,
						"bubble_id":  thinkingBubbleID,
					}
					jsonData, _ := json.Marshal(thinkingEndData)
					writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
					writer.Flush()
					thinkingBubbleID = "" // 重置，避免重复发送
					thinkingStarted = false
				}

				for _, toolCallDelta := range delta.ToolCalls {
					// 查找或创建对应的工具调用
					index := *toolCallDelta.Index

					// 扩展toolCalls数组
					for len(toolCalls) <= index {
						toolCalls = append(toolCalls, ark.ToolCall{})
					}

					// 累积工具调用信息
					if toolCallDelta.ID != "" {
						toolCalls[index].ID = toolCallDelta.ID
					}
					if toolCallDelta.Type != "" {
						toolCalls[index].Type = toolCallDelta.Type
					}
					if toolCallDelta.Function.Name != "" {
						toolCalls[index].Function.Name = toolCallDelta.Function.Name

						// 为该工具调用生成唯一的bubble_id
						if _, exists := toolBubbleIDs[index]; !exists {
							toolBubbleIDs[index] = fmt.Sprintf("tool_%s_%d", toolCallDelta.Function.Name, time.Now().UnixNano())
						}

						// 发送工具调用开始信号
						toolStartData := map[string]interface{}{
							"type":       "tool_start",
							"tool_name":  toolCallDelta.Function.Name,
							"session_id": agent.sessionID,
							"bubble_id":  toolBubbleIDs[index],
						}
						jsonData, _ := json.Marshal(toolStartData)
						writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
						writer.Flush()
					}
					if toolCallDelta.Function.Arguments != "" {
						toolCalls[index].Function.Arguments += toolCallDelta.Function.Arguments
					}
				}
			}
		}

		stream.Close()

		// 如果 thinking 结束了但还没发送 thinking_end（比如流结束时）
		if thinkingStarted && thinkingBubbleID != "" {
			thinkingEndData := map[string]interface{}{
				"type":       "thinking_end",
				"session_id": agent.sessionID,
				"bubble_id":  thinkingBubbleID,
			}
			jsonData, _ := json.Marshal(thinkingEndData)
			writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
			writer.Flush()
		}

		// 构建完整的助手消息
		assistantMessage := ark.ChatCompletionMessage{
			Role:             ark.ChatMessageRoleAssistant,
			ReasoningContent: fullReasoning.String(),
			Content:          fullContent.String(),
		}

		// 如果有工具调用
		if len(toolCalls) > 0 {
			assistantMessage.ToolCalls = toolCalls
			agent.history = append(agent.history, assistantMessage)

			// 执行所有工具调用
			for index, toolCall := range toolCalls {
				// 获取该工具调用的bubble_id
				bubbleID := toolBubbleIDs[index]

				// 执行工具
				toolResult, err := agent.ExecuteTool(toolCall)
				if err != nil {
					toolResult = fmt.Sprintf("工具执行失败: %v", err)
				}

				// 流式输出工具结果（如果需要显示）
				if toolCall.Function.Name != "get_article_detail" {
					agent.streamToolResult(toolResult, writer, bubbleID)
				}

				// 添加工具结果到历史
				agent.history = append(agent.history, ark.ChatCompletionMessage{
					Role:       ark.ChatMessageRoleTool,
					Content:    toolResult,
					ToolCallID: toolCall.ID,
					Name:       toolCall.Function.Name,
				})

				// 发送工具调用结束信号
				toolEndData := map[string]interface{}{
					"type":       "tool_end",
					"tool_name":  toolCall.Function.Name,
					"session_id": agent.sessionID,
					"bubble_id":  bubbleID,
				}
				jsonData, _ := json.Marshal(toolEndData)
				writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
				writer.Flush()
			}

			// 继续下一轮迭代
			continue
		} else {
			// 没有工具调用，添加消息到历史并结束
			agent.history = append(agent.history, assistantMessage)
			break
		}
	}

	if iteration >= maxIterations {
		errorData := map[string]interface{}{
			"type":    "error",
			"content": "达到最大迭代次数，对话终止",
		}
		jsonData, _ := json.Marshal(errorData)
		writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
		writer.Flush()
	}

	return nil
}

// streamContent 流式输出内容
func (agent *AIChat) streamContent(content string, writer gin.ResponseWriter, bubbleID string) {
	chunkSize := 20
	runes := []rune(content)

	for i := 0; i < len(runes); i += chunkSize {
		end := i + chunkSize
		if end > len(runes) {
			end = len(runes)
		}

		chunk := string(runes[i:end])

		chunkData := map[string]interface{}{
			"type":       "content",
			"content":    chunk,
			"session_id": agent.sessionID,
			"bubble_id":  bubbleID,
		}

		jsonData, err := json.Marshal(chunkData)
		if err != nil {
			// 如果JSON序列化失败，使用简单的转义
			escapedContent := strings.ReplaceAll(chunk, `\`, `\\`)
			escapedContent = strings.ReplaceAll(escapedContent, `"`, `\"`)
			escapedContent = strings.ReplaceAll(escapedContent, "\n", `\n`)
			escapedContent = strings.ReplaceAll(escapedContent, "\r", `\r`)
			escapedContent = strings.ReplaceAll(escapedContent, "\t", `\t`)
			jsonData = []byte(fmt.Sprintf(`{"type":"content","content":"%s","session_id":"%s","bubble_id":"%s"}`, escapedContent, agent.sessionID, bubbleID))
		}

		writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
		writer.Flush()

		// 添加小延迟以模拟流式效果
		time.Sleep(50 * time.Millisecond)
	}
}

// streamToolResult 流式输出工具结果
func (agent *AIChat) streamToolResult(result string, writer gin.ResponseWriter, bubbleID string) {
	chunkSize := 30 // 工具结果可以稍微大一些
	runes := []rune(result)

	for i := 0; i < len(runes); i += chunkSize {
		end := i + chunkSize
		if end > len(runes) {
			end = len(runes)
		}

		chunk := string(runes[i:end])

		toolResultData := map[string]interface{}{
			"type":       "tool_result",
			"content":    chunk,
			"session_id": agent.sessionID,
			"bubble_id":  bubbleID,
		}

		jsonData, err := json.Marshal(toolResultData)
		if err != nil {
			// 如果JSON序列化失败，使用简单的转义
			escapedContent := strings.ReplaceAll(chunk, `\`, `\\`)
			escapedContent = strings.ReplaceAll(escapedContent, `"`, `\"`)
			escapedContent = strings.ReplaceAll(escapedContent, "\n", `\n`)
			escapedContent = strings.ReplaceAll(escapedContent, "\r", `\r`)
			escapedContent = strings.ReplaceAll(escapedContent, "\t", `\t`)
			jsonData = []byte(fmt.Sprintf(`{"type":"tool_result","content":"%s","session_id":"%s","bubble_id":"%s"}`, escapedContent, agent.sessionID, bubbleID))
		}

		writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
		writer.Flush()

		// 添加小延迟以模拟流式效果
		time.Sleep(30 * time.Millisecond)
	}
}

// SaveSession 保存会话（需要传入userID）
func (agent *AIChat) SaveSession(userID int) error {
	sessionName := "新对话"
	if len(agent.history) > 1 {
		for _, msg := range agent.history[1:] {
			if msg.Role == ark.ChatMessageRoleUser {
				sessionName = msg.Content
				break
			}
		}
	}

	// 确保sessionName是有效的UTF-8字符串
	sessionName = strings.ToValidUTF8(sessionName, "?")
	// 限制sessionName长度，避免数据库字段长度问题
	if len([]rune(sessionName)) > 1000 {
		sessionName = string([]rune(sessionName)[:1000])
	}

	session := ChatSession{
		ID:        agent.sessionID,
		Name:      sessionName,
		History:   agent.history,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	sessionJSON, err := json.Marshal(session)
	if err != nil {
		return fmt.Errorf("编码会话数据失败: %v", err)
	}

	// 确保JSON数据是有效的UTF-8
	jsonStr := strings.ToValidUTF8(string(sessionJSON), "?")

	var count int
	err = agent.db.Get(&count, "SELECT COUNT(*) FROM chat_sessions WHERE session_id = ?", agent.sessionID)
	if err != nil {
		return fmt.Errorf("检查会话存在性失败: %v", err)
	}

	currentTime := helper.GetCurrentTimeString()

	if count > 0 {
		_, err = agent.db.Exec(`
			UPDATE chat_sessions 
			SET session_name = ?, content = ?, updated_at = ? 
			WHERE session_id = ?
		`, sessionName, jsonStr, currentTime, agent.sessionID)
	} else {
		_, err = agent.db.Exec(`
			INSERT INTO chat_sessions (session_id, session_name, content, user_id, created_at, updated_at) 
			VALUES (?, ?, ?, ?, ?, ?)
		`, agent.sessionID, sessionName, jsonStr, userID, currentTime, currentTime)
	}

	if err != nil {
		return fmt.Errorf("保存会话到数据库失败: %v", err)
	}

	return nil
}

// LoadSession 加载会话（需要传入userID进行权限验证）
func (agent *AIChat) LoadSession(sessionID string, userID int) error {
	var contentJSON string
	err := agent.db.Get(&contentJSON, "SELECT content FROM chat_sessions WHERE session_id = ? AND user_id = ?", sessionID, userID)
	if err != nil {
		if err == sql.ErrNoRows {
			return fmt.Errorf("会话不存在或无权访问: %s", sessionID)
		}
		return fmt.Errorf("从数据库加载会话失败: %v", err)
	}

	var session ChatSession
	if err := json.Unmarshal([]byte(contentJSON), &session); err != nil {
		return fmt.Errorf("解码会话数据失败: %v", err)
	}

	agent.history = session.History
	agent.sessionID = session.ID
	return nil
}

func GetAllContentModel(c *gin.Context) {
	models := agent_config["content"]
	modelsMap := []map[string]string{}
	for model, modelInfo := range models {
		modelsMap = append(modelsMap, map[string]string{
			"model":      model,
			"model_name": modelInfo["model_name"],
			"icon_url":   modelInfo["icon_url"],
		})
	}
	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"models":  modelsMap,
	})
}

// // Chat 支持工具调用的AIChat聊天接口（模拟流式，兼容旧版）
// func Chat(c *gin.Context) {
// 	var req ChatRequest
// 	if err := c.ShouldBindJSON(&req); err != nil {
// 		c.JSON(http.StatusBadRequest, ChatResponse{
// 			Success: false,
// 			Error:   err.Error(),
// 		})
// 		return
// 	}

// 	// 创建AI Agent实例，如果提供了sessionID则使用它
// 	agent := NewAIChatWithSession(
// 		agent_config["content"][req.Model]["api_key"],
// 		agent_config["content"][req.Model]["base_url"],
// 		agent_config["content"][req.Model]["model"],
// 		req.SessionID, // 直接传入sessionID，如果为空则生成新的
// 	)

// 	// 如果提供了sessionID，尝试加载该会话
// 	if req.SessionID != "" {
// 		if err := agent.LoadSession(req.SessionID); err != nil {
// 			// 如果加载失败，使用新生成的sessionID
// 			fmt.Printf("加载会话失败，使用新会话: %v\n", err)
// 		}
// 	}

// 	// 流式响应
// 	c.Header("Content-Type", "text/event-stream; charset=utf-8")
// 	c.Header("Cache-Control", "no-cache")
// 	c.Header("Connection", "keep-alive")
// 	c.Header("Access-Control-Allow-Origin", "*")
// 	c.Header("Access-Control-Allow-Headers", "Content-Type")
// 	c.Header("Access-Control-Allow-Methods", "POST, OPTIONS")

// 	// 使用Agent进行流式聊天（支持工具调用）
// 	if err := agent.ChatWithToolsStream(req.Message, c.Writer); err != nil {
// 		c.JSON(http.StatusInternalServerError, ChatResponse{
// 			Success: false,
// 			Error:   err.Error(),
// 		})
// 		return
// 	}

// 	// 自动保存会话
// 	if err := agent.SaveSession(); err != nil {
// 		fmt.Printf("警告: 自动保存会话失败: %v\n", err)
// 	}

// 	// 发送结束信号
// 	endData := fmt.Sprintf(`{"type":"end","session_id":"%s"}`, agent.sessionID)
// 	c.Writer.WriteString(fmt.Sprintf("data: %s\n\n", endData))
// 	c.Writer.WriteString("data: [DONE]\n\n")
// 	c.Writer.Flush()
// }

// ChatStream 真正的流式聊天接口，支持工具调用和思考过程展示
func ChatStream(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, ChatResponse{
			Success: false,
			Error:   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	var req ChatRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, ChatResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	// 创建AI Agent实例，如果提供了sessionID则使用它
	agent := NewAIChatWithSession(
		agent_config["content"][req.Model]["api_key"],
		agent_config["content"][req.Model]["base_url"],
		agent_config["content"][req.Model]["model"],
		req.SessionID, // 直接传入sessionID，如果为空则生成新的
	)

	// 如果提供了sessionID，尝试加载该会话
	if req.SessionID != "" {
		if err := agent.LoadSession(req.SessionID, userID); err != nil {
			// 如果加载失败，使用新生成的sessionID
			fmt.Printf("加载会话失败，使用新会话: %v\n", err)
		}
	}

	// 设置SSE响应头
	c.Header("Content-Type", "text/event-stream; charset=utf-8")
	c.Header("Cache-Control", "no-cache")
	c.Header("Connection", "keep-alive")
	c.Header("Access-Control-Allow-Origin", "*")
	c.Header("Access-Control-Allow-Headers", "Content-Type")
	c.Header("Access-Control-Allow-Methods", "POST, OPTIONS")

	// 使用真正的流式聊天（支持工具调用和思考过程）
	if err := agent.ChatWithToolsStreamReal(req.Message, c.Writer); err != nil {
		errorData := map[string]interface{}{
			"type":    "error",
			"content": err.Error(),
		}
		jsonData, _ := json.Marshal(errorData)
		c.Writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
		c.Writer.Flush()
		return
	}

	// 自动保存会话
	if err := agent.SaveSession(userID); err != nil {
		fmt.Printf("警告: 自动保存会话失败: %v\n", err)
	}

	// 发送结束信号
	endData := fmt.Sprintf(`{"type":"end","session_id":"%s"}`, agent.sessionID)
	c.Writer.WriteString(fmt.Sprintf("data: %s\n\n", endData))
	c.Writer.WriteString("data: [DONE]\n\n")
	c.Writer.Flush()
}

// 获取会话名称的辅助函数
func getSessionName(history []ark.ChatCompletionMessage) string {
	if len(history) > 1 {
		for _, msg := range history[1:] {
			if msg.Role == ark.ChatMessageRoleUser {
				content := msg.Content
				return content
			}
		}
	}
	return "新对话"
}

// 创建新会话
func CreateSession(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, SessionResponse{
			Success: false,
			Error:   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	// 创建新的聊天机器人实例
	agent := NewAIChatWithSession(
		agent_config["content"]["gemini_flash"]["api_key"],
		agent_config["content"]["gemini_flash"]["base_url"],
		agent_config["content"]["gemini_flash"]["model"],
		"",
	)

	// 保存会话
	if err := agent.SaveSession(userID); err != nil {
		c.JSON(http.StatusInternalServerError, SessionResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	session := ChatSession{
		ID:        agent.sessionID,
		Name:      "新对话",
		History:   agent.history,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	c.JSON(http.StatusOK, SessionResponse{
		Session: session,
		Success: true,
	})
}

// 加载会话
func LoadSession(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, SessionResponse{
			Success: false,
			Error:   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	sessionID := c.Param("id")

	agent := NewAIChatWithSession(
		agent_config["content"]["gemini_flash"]["api_key"],
		agent_config["content"]["gemini_flash"]["base_url"],
		agent_config["content"]["gemini_flash"]["model"],
		sessionID,
	)

	if err := agent.LoadSession(sessionID, userID); err != nil {
		c.JSON(http.StatusNotFound, SessionResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	session := ChatSession{
		ID:        agent.sessionID,
		Name:      getSessionName(agent.history),
		History:   agent.history,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	c.JSON(http.StatusOK, SessionResponse{
		Session: session,
		Success: true,
	})
}

// 删除会话
func DeleteSession(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"success": false,
			"error":   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	sessionID := c.Param("id")

	if err := deleteSession(sessionID, userID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": false,
			"error":   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "会话删除成功",
	})
}

// 获取所有会话
func GetSessions(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, SessionListResponse{
			Success: false,
			Error:   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	sessions, err := ListSessions(userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, SessionListResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, SessionListResponse{
		Sessions: sessions,
		Success:  true,
	})
}

// ListSessions 从数据库列出指定用户的所有会话
func ListSessions(userID int) ([]ChatSession, error) {
	var rows []SessionRow
	err := database.Db.Select(&rows, `
		SELECT session_id, session_name, content, user_id, created_at, updated_at 
		FROM chat_sessions 
		WHERE user_id = ?
		ORDER BY updated_at DESC
	`, userID)
	if err != nil {
		return nil, fmt.Errorf("查询会话列表失败: %v", err)
	}

	var sessions []ChatSession
	for _, row := range rows {
		var session ChatSession
		if err := json.Unmarshal([]byte(row.Content), &session); err != nil {
			continue
		}

		// 更新从数据库读取的时间戳
		session.CreatedAt = row.CreatedAt
		session.UpdatedAt = row.UpdatedAt
		sessions = append(sessions, session)
	}

	return sessions, nil
}

// DeleteSession 从数据库删除会话（需要传入userID进行权限验证）
func deleteSession(sessionID string, userID int) error {
	result, err := database.Db.Exec("DELETE FROM chat_sessions WHERE session_id = ? AND user_id = ?", sessionID, userID)
	if err != nil {
		return fmt.Errorf("删除会话失败: %v", err)
	}

	rowsAffected, err := result.RowsAffected()
	if err != nil {
		return fmt.Errorf("获取删除结果失败: %v", err)
	}

	if rowsAffected == 0 {
		return fmt.Errorf("会话不存在或无权删除: %s", sessionID)
	}

	return nil
}

// processImageURL 下载并上传到MinIO
func downloadImageAndUploadToMinIO(imageURL string) (string, error) {
	// 下载图片
	imageFile, err := downloadImage(imageURL)
	if err != nil {
		log.Printf("下载图片失败 %s: %v", imageURL, err)
		return imageURL, nil // 下载失败时返回原URL
	}
	defer func() {
		imageFile.Close()
		os.Remove(imageFile.Name()) // 清理临时文件
	}()

	// 上传到MinIO
	newURL, err := uploadImageToMinIO(imageFile, imageURL)
	if err != nil {
		log.Printf("上传图片失败 %s: %v", imageURL, err)
		return imageURL, nil // 上传失败时返回原URL
	}

	return newURL, nil
}

func downloadImage(imageURL string) (*os.File, error) {
	client := &http.Client{
		Timeout: 30 * time.Second,
	}
	headers := map[string]string{
		"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
		"Accept":          "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
		"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
	}

	// 创建HTTP请求
	req, err := http.NewRequest("GET", imageURL, nil)
	if err != nil {
		return nil, fmt.Errorf("创建图片请求失败: %v", err)
	}

	// 设置请求头
	for key, value := range headers {
		req.Header.Set(key, value)
	}

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("下载图片失败: %v", err)
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("下载图片失败，状态码: %d", resp.StatusCode)
	}

	// 检查Content-Type是否为图片
	contentType := resp.Header.Get("Content-Type")
	if !strings.HasPrefix(contentType, "image/") {
		return nil, fmt.Errorf("不是有效的图片类型: %s", contentType)
	}

	// 创建临时文件
	tempFile, err := os.CreateTemp("", "crawler-image-*.tmp")
	if err != nil {
		return nil, fmt.Errorf("创建临时文件失败: %v", err)
	}

	// 复制图片内容到临时文件
	_, err = io.Copy(tempFile, resp.Body)
	if err != nil {
		tempFile.Close()
		os.Remove(tempFile.Name())
		return nil, fmt.Errorf("保存图片失败: %v", err)
	}

	// 重置文件指针到开头
	_, err = tempFile.Seek(0, 0)
	if err != nil {
		tempFile.Close()
		os.Remove(tempFile.Name())
		return nil, fmt.Errorf("重置文件指针失败: %v", err)
	}

	return tempFile, nil
}

func uploadImageToMinIO(imageFile *os.File, originalURL string) (string, error) {
	// 从原始URL中提取文件名
	parsedURL, err := url.Parse(originalURL)
	if err != nil {
		return "", fmt.Errorf("解析图片URL失败: %v", err)
	}

	// 获取文件扩展名
	ext := filepath.Ext(parsedURL.Path)
	if ext == "" {
		ext = ".jpg" // 默认扩展名
	}

	// 生成新的文件名
	fileName := minio.GenerateFileName() + ext

	// 上传到MinIO
	newURL, err := minio.UploadImage(fileName, imageFile)
	if err != nil {
		return "", fmt.Errorf("上传图片到MinIO失败: %v", err)
	}

	log.Printf("图片上传成功: %s", newURL)
	return newURL, nil
}
